package com.tutorial.demo.threadDemo;

public class ThreadStart {
    public static String str = "lock";
    public static Object object = new Object();
    public static void main(String[] args) {
        Thread t = new Thread1();
        t.setName("Thread1");
        t.start();
        Runnable r1 = new Runnable1();
        Thread t2 = new Thread(r1);
        Thread t3 = new Thread(r1);
        try {
            //内部调用了wait()
            //wait方法调用之前要释放锁对象，意味着之前已经获得了锁对象
            //源码中join方法是synchronized,意味着以当前对象作为锁对象
            //含义如下，t2.wait()意味着当前线程在t2的等待队列中等待，而不是t2进入等待状态
            //不信你看下面的例子
            //object.wait()意味着当前线程在object锁对象的等待队列中进行等待，而不是object进入等待状态
//            synchronized (t2){
//                t2.wait();
//            }
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t2.setName("Thread2");
        t3.setName("Thread3");
        t2.start();

    }



}
class Thread1 extends Thread{
    @Override
    public void run() {
        synchronized (ThreadStart.object){
            //将object的等待队列中线程唤醒，
            //当object的等待队列中有多个线程时，取出队头的线程去抢锁，跟其他的synchronized抢锁，抢到了线程就由WAITING变为RUANNABLE，
            //抢不到就线程就进入object的同步队列，状态变为BLOCKED。跟synchronized同
            //线程全部变为BLOCKED,进入object的同步队列，继续进行抢锁，抢到锁线程变为RUANNABLE，其他线程继续进入object的等待队列，变为BLOCKED状态
            ThreadStart.object.notify();
            System.out.println(Thread.currentThread().getName()+"is running");
        }

    }
}

class Runnable1 implements Runnable{

    @Override
    public void run() {
        //当有多个线程同时获取这个锁时，获取到锁的线程继续执行
        //1.获取不到锁的线程进入object的同步队列 2.这个线程的状态改为BLOCKED
        //当持有object锁的线程将object锁释放之后，object同步队列中多个线程开始抢锁，抢到这个锁的线程从BLOCKED状态从RUANNABLE转态，抢不到锁的线程继续
        synchronized (ThreadStart.object){
            try {
                // 1.释放object锁，意味着之前就已经获得了lock对象
                // 2.线程变为WAITING状态 3.线程进入object的等待队列
                // 调用wait必须有object monitor，必须在synchronized里面？
                ThreadStart.object.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"is running");
        }
    }
}
